package cn.unknowpupil.service.system.impl;

import cn.unknowpupil.common.core.exceptions.HealthException;
import cn.unknowpupil.common.core.utils.StringUtils;
import cn.unknowpupil.common.mybatis.enums.StateEnum;
import cn.unknowpupil.common.security.utils.SecurityUtils;
import cn.unknowpupil.domain.dto.TreeSelect;
import cn.unknowpupil.domain.system.SysDept;
import cn.unknowpupil.domain.system.SysDictType;
import cn.unknowpupil.domain.system.SysRole;
import cn.unknowpupil.mapper.system.SysDeptMapper;
import cn.unknowpupil.mapper.system.SysRoleMapper;
import cn.unknowpupil.mapper.system.SysUserMapper;
import cn.unknowpupil.service.system.ISysDeptService;
import cn.unknowpupil.service.system.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created at 2020-10-21 by  w10g <br>
 * Initialize SysDept  ... <br>
 * 部门表 核心业务处理实现类
 *
 * @author unknowpupil
 * @since 0.0.1
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysRoleMapper roleMapper;
    /**
     * 新增
     *
     * @param sysDept {@link SysDept}  部门表
     * @return {@link SysDept}
     */
    @Override
    public boolean create(SysDept sysDept) {
        boolean b = checkDeptNameUnique(sysDept);
        if (b) {
            return save(sysDept);
        } else {
            throw new HealthException("新增部门'" + sysDept.getDeptName() + "'失败，部门名称已存在");
        }


    }

    private boolean checkDeptNameUnique(SysDept dept) {

        LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDept::getDeptName, dept.getDeptName());
        wrapper.eq(SysDept::getParentId, dept.getParentId());
        SysDept info = baseMapper.selectOne(wrapper);

        Long deptId = StringUtils.isNull(dept.getId()) ? -1L : dept.getId();

        if (null != info && !info.getId().equals(deptId)) {
            return false;
        } else {
            return true;
        }


    }

    /**
     * 详情
     *
     * @param id {@code Long}   SysDept ID
     * @return {@link SysDept}
     */
    @Override
    public SysDept info(Long id) {
        return getById(id);
    }

    /**
     * 删除
     *
     * @param id {@code Long}   SysDept ID
     * @return {@link SysDept}
     */
    @Override
    public boolean delete(Long id) {
        LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDept::getParentId, id);
        Integer count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new HealthException("存在下级部门,不允许删除");
        }
        count = userMapper.checkDeptExistUser(id);
        if (count > 0) {
            throw new HealthException("部门存在用户,不允许删除");
        }
       return super.removeById(id);


    }


    /**
     * 修改
     *
     * @param sysDept {@link SysDept}  部门表
     * @return {@link SysDept}
     */
    @Override
    public boolean update(SysDept sysDept) {
        boolean result = checkDeptNameUnique(sysDept);
        if (!result) {
            throw new HealthException("修改部门'" + sysDept.getDeptName() + "'失败，部门名称已存在");
        }
        if (sysDept.getParentId().equals(sysDept.getId())) {
            throw new HealthException("修改部门'" + sysDept.getDeptName() + "'失败，上级部门不能是自己");
        }
        int i = baseMapper.selectNormalChildrenDeptById(sysDept.getId());
        if (StringUtils.equals(StateEnum.INACTIVE.getStatus(), sysDept.getStatus()) && i > 0) {
            throw new HealthException("无法修改，该部门包含未停用的子部门！");
        }

        SysDept newParentDept = baseMapper.selectById(sysDept.getParentId());
        SysDept oldDept = baseMapper.selectById(sysDept.getId());
        if (newParentDept != null && oldDept != null) {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getId();
            String oldAncestors = oldDept.getAncestors();
            sysDept.setAncestors(newAncestors);
            updateDeptChildren(sysDept.getId(), newAncestors, oldAncestors);
        }
        boolean update = updateById(sysDept);
        if (sysDept.getStatus().equals(StateEnum.ACTIVE.getStatus())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatus(sysDept);
        }
        return update;
    }

    private void updateParentDeptStatus(SysDept dept) {
        String updateBy = dept.getUpdateBy();
        dept = baseMapper.selectById(dept.getId());
        dept.setUpdateBy(updateBy);
        baseMapper.updateDeptStatus(dept);
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    private void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = baseMapper.selectChildrenDeptById(deptId);
        for (SysDept child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            super.updateBatchById(children);
        }
    }


    /**
     * 分页
     *
     * @param sysDept {@link SysDept}
     * @return {@code IPage<SysDept>}
     */
    @Override
    public List<SysDept> selectList(SysDept sysDept) {

        LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
        if (null != sysDept.getParentId()) {
            wrapper.eq(SysDept::getParentId, sysDept.getParentId());
        }
        if (StringUtils.isNotBlank(sysDept.getDeptName())) {
            wrapper.like(SysDept::getDeptName, sysDept.getDeptName());
        }
        if (StringUtils.isNotBlank(sysDept.getStatus())) {
            wrapper.eq(SysDept::getStatus, sysDept.getStatus());
        }
        wrapper.orderByAsc(SysDept::getParentId).orderByAsc(SysDept::getOrderNum);
        return super.list(wrapper);

    }

    @Override
    public List<SysDept> selectDeptList(SysDept sysDept) {
        LambdaQueryWrapper<SysDept> query = new LambdaQueryWrapper<>();
        if (sysDept.getParentId() != null && sysDept.getParentId() != 0) {
            query.eq(SysDept::getParentId, sysDept.getParentId());
        }
        if (StringUtils.isNotBlank(sysDept.getDeptName())) {
            query.like(SysDept::getDeptName, sysDept.getDeptName());
        }
        if (sysDept.getStatus() != null) {
            query.eq(SysDept::getStatus, sysDept.getStatus());
        }
        query.orderByAsc(SysDept::getParentId).orderByAsc(SysDept::getOrderNum);
        return baseMapper.selectList(query);
    }

    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts) {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts) {
        List<SysDept> returnList = new ArrayList<SysDept>();
        List<Long> tempList = new ArrayList<Long>();
        for (SysDept dept : depts) {
            tempList.add(dept.getId());
        }
        for (Iterator<SysDept> iterator = depts.iterator(); iterator.hasNext(); ) {
            SysDept dept = (SysDept) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    @Override
    public List<Long> selectDeptListByRoleId(Long roleId) {
        SysRole role = roleMapper.selectRoleById(roleId);
        return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());

    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDept> list, SysDept t) {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     *
     * @param list
     * @param t
     * @return
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
        List<SysDept> tlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext()) {
            SysDept n = (SysDept) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     *
     * @param list
     * @param t
     * @return
     */
    private boolean hasChild(List<SysDept> list, SysDept t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}
